home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- Project : MacPerl - Real Perl Application
- File : MPScript.c - Handle scripts
- Author : Matthias Neeracher
- Language : MPW C
-
- $Log: MPScript.c,v $
- Revision 1.2 1994/05/04 02:54:19 neeri
- Always keep the right resource file in front.
-
- Revision 1.1 1994/02/27 23:01:56 neeri
- Initial revision
-
- Revision 0.2 1993/10/14 00:00:00 neeri
- Run front window
-
- Revision 0.1 1993/08/17 00:00:00 neeri
- Set up correct default directory
-
- *********************************************************************/
-
- #include <AERegistry.h>
- #include <String.h>
- #include <TFileSpec.h>
- #include <setjmp.h>
- #include <sys/types.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <Signal.h>
- #include <StandardFile.h>
- #include <Resources.h>
- #include <PLStringFuncs.h>
- #include <SysEqu.h>
-
- #include "MPScript.h"
- #include "MPWindow.h"
- #include "MPAppleEvents.h"
-
- int run_perl(int, char **, char **);
- void reenter();
- extern Handle PerlReply;
- extern int PerlQuit;
- extern char gPseudoFileName[];
-
- #ifndef RUNTIME
- pascal Boolean GetScriptFilter(ParmBlkPtr info, void * data)
- {
- #pragma unused(data)
- #else
- pascal Boolean GetScriptFilter(ParmBlkPtr info)
- {
- #endif
- switch (info->fileParam.ioFlFndrInfo.fdType) {
- case 'APPL':
- switch (info->fileParam.ioFlFndrInfo.fdCreator) {
- case MPRtSig:
- return false;
- case MPAppSig:
- return !info->fileParam.ioFlLgLen;
- default:
- return true;
- }
- case 'TEXT':
- return false;
- default:
- return true;
- }
- }
-
- #ifndef RUNTIME
-
- #define gsDebugItem 10
-
- pascal short GetScriptHook(short item, DialogPtr dlg, void * params)
- {
- short kind;
- ControlHandle dbg;
- Rect r;
- Boolean * par = (Boolean *) params;
-
- if (GetWRefCon(dlg) != 'stdf')
- return item;
-
- switch (item) {
- case sfHookFirstCall:
- *par = false;
-
- return sfHookFirstCall;
- case gsDebugItem:
- *par = !*par;
-
- GetDItem(dlg, item, &kind, (Handle *) &dbg, &r);
-
- SetCtlValue(dbg, *par);
-
- return sfHookNullEvent;
- default:
- return item;
- }
- }
-
- static void SendScriptEvent(
- DescType argType,
- Ptr argPtr,
- Handle argHdl,
- Size argSize,
- Boolean debug)
- {
- OSErr err;
- AppleEvent cmd, repl;
- AEAddressDesc addr;
-
- if (err = MakeSelfAddress(&addr))
- goto failedAddress;
-
- if (err =
- AECreateAppleEvent(
- kAEMiscStandards, kAEDoScript, &addr,
- kAutoGenerateReturnID, kAnyTransactionID,
- &cmd)
- )
- goto failedAppleEvent;
-
- if (argHdl) {
- HLock(argHdl);
- argPtr = *argHdl;
- }
-
- if (err = AEPutParamPtr(&cmd, keyDirectObject, argType, argPtr, argSize))
- goto failedParam;
-
- if (debug)
- if (err =
- AEPutParamPtr(
- &cmd, 'DEBG',
- typeBoolean, (Ptr) &debug, sizeof(Boolean))
- )
- goto failedParam;
-
- err =
- AESend(
- &cmd,
- &repl,
- kAENoReply+kAEAlwaysInteract,
- kAENormalPriority,
- kAEDefaultTimeout,
- nil,
- nil);
-
- AEDisposeDesc(&repl);
- failedParam:
- if (argHdl)
- HUnlock(argHdl);
-
- AEDisposeDesc(&cmd);
- failedAppleEvent:
- AEDisposeDesc(&addr);
- failedAddress:
- ;
- }
-
- static SFTypeList PerlFileTypes = {'TEXT', 'APPL'};
-
- pascal void DoScriptMenu(short theItem)
- {
- StandardFileReply reply;
- Point where;
- Boolean debug;
-
- where.h = where.v = -1;
-
- switch (theItem) {
- case pmRun:
- CustomGetFile(
- GetScriptFilter,
- 2,
- PerlFileTypes,
- &reply,
- GetScriptDialog,
- where,
- GetScriptHook,
- (ModalFilterYDProcPtr) nil,
- nil,
- (ActivateYDProcPtr) nil,
- &debug);
- if (reply.sfGood)
- SendScriptEvent(typeFSS, (Ptr) &reply.sfFile, nil, sizeof(FSSpec), debug);
- break;
- case pmRunFront:
- {
- DPtr doc = DPtrFromWindowPtr(FrontWindow());
-
- if (!doc || doc->kind != kDocumentWindow)
- break;
-
- if (doc->dirty || !doc->u.reg.everSaved) {
- if (doc->u.reg.everSaved)
- strcpy(gPseudoFileName, FSp2FullPath(&doc->theFSSpec));
- else
- getwtitle(FrontWindow(), gPseudoFileName);
-
- SendScriptEvent(
- typeChar, nil, (*doc->theText)->hText,
- GetHandleSize((*doc->theText)->hText),
- false);
- } else
- SendScriptEvent(typeFSS, (Ptr) &doc->theFSSpec, nil, sizeof(FSSpec), false);
- }
- break;
- }
- }
-
- #endif
-
- static char * PerlArgs[] = {
- "MacPerl",
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- };
-
- static char * PerlEnviron[] = {
- "PERLDB=require \"macperldb.pl\"",
- 0,
- 0
- };
-
- extern char * perldbgname;
-
- pascal void InitPerlEnviron()
- {
- char ** env = PerlEnviron;
- char * eq;
-
- while (*env)
- if (eq = strchr(*env++, '='))
- *eq = 0;
-
- perldbgname = "Dev:Console:Debug Log";
- }
-
- char * getenv(char * var)
- {
- char ** env;
-
- for (env = PerlEnviron; *env; ++env)
- if (!strcmp(*env, var))
- return *env + strlen(*env) + 1;
-
- return nil;
- }
-
- static jmp_buf ExitPerl;
-
- void real_exit(int status);
-
- void exit(int status)
- {
- if (gRunningPerl)
- longjmp(ExitPerl, -status);
- else
- real_exit(status);
- }
-
- typedef void (*atexitfn)();
-
- static atexitfn PerlExitFn[20];
- static int PerlExitCnt;
-
- int real_atexit(atexitfn func);
-
- int atexit(atexitfn func)
- {
- if (gRunningPerl)
- PerlExitFn[PerlExitCnt++] = func;
- else
- return real_atexit(func);
-
- return 0;
- }
-
- void CleanupPerl()
- {
- int i;
- extern FILE * _lastbuf;
-
- UseResFile(gAppFile);
-
- // Borrowed from GUSI
-
- // Close stdio files (necessary to flush buffers)
- // This implementation is not nice, but who cares ?
- // In case you wonder, _iob is defined in <stdio.h>
-
- for (i = 0; _iob+i<_lastbuf; i++)
- fflush(_iob+i);
-
- for (i = 0; _iob+i<_lastbuf; i++)
- fclose(_iob+i);
-
- // Close all files
-
- for (i = 0; i<FD_SETSIZE; ++i)
- close(i);
-
- while (PerlExitCnt)
- PerlExitFn[--PerlExitCnt]();
-
- UseResFile(gAppFile);
- reenter();
-
- open("Dev:Console", O_RDONLY);
- open("Dev:Console", O_WRONLY);
- open("Dev:Console", O_WRONLY);
-
- fopen("Dev:Console", "r");
- fopen("Dev:Console", "w");
- fopen("Dev:Console", "w");
- }
-
- enum {
- extractDone = -4,
- extractDir = -3,
- extractCpp = -2,
- extractDebug = -1
- };
-
- typedef char * (*ArgExtractor)(void * data, int index);
-
- pascal void RunScript(ArgExtractor extractor, void * data)
- {
- int ArgC;
- short resFile;
- Handle libs;
- Str255 lib;
- char * res;
- int i;
-
- PtrToHand("PERLLIB", &libs, 8);
-
- resFile = CurResFile();
- UseResFile(gPrefsFile);
-
- for (ArgC = 1; ; ++ArgC) {
- GetIndString(lib, LibraryPaths, ArgC);
-
- if (!lib[0])
- break;
-
- if (ArgC > 1)
- PtrAndHand(",", libs, 1);
-
- PtrAndHand(lib+1, libs, lib[0]);
- }
-
- UseResFile(resFile);
-
- if (PerlEnviron[1])
- DisposePtr(PerlEnviron[1]);
-
- PerlEnviron[1] = NewPtr(GetHandleSize(libs)+1);
- BlockMove(*libs, PerlEnviron[1], GetHandleSize(libs));
- PerlEnviron[1][GetHandleSize(libs)] = 0;
- DisposeHandle(libs);
-
- ArgC = 1;
-
- {
- char path[256];
-
- strcpy(path, extractor(data, extractDir));
- chdir(path);
- }
-
- if ((res = extractor(data, extractDebug)) && *res == 'y')
- PerlArgs[ArgC++] = "-d";
-
- if ((res = extractor(data, extractCpp)) && *res == 'y')
- PerlArgs[ArgC++] = "-P";
-
- if (res = extractor(data, 1)) {
- if (gPerlPrefs.checkType && !gPseudoFile)
- PerlArgs[ArgC++] = "-x";
-
- PerlArgs[ArgC++] = res;
-
- for (i=2; PerlArgs[ArgC] = extractor(data, i); ++i, ++ArgC);
- }
-
- extractor(data, extractDone);
-
- UseResFile(gAppFile);
-
- gRunningPerl = true;
- PerlQuit = 0;
- ShowWindowStatus();
-
- signal(SIGINT, exit);
-
- if (!setjmp(ExitPerl))
- run_perl(ArgC, PerlArgs, PerlEnviron);
-
- CleanupPerl();
- gRunningPerl = false;
-
- if (gScriptFile != gAppFile) {
- CloseResFile(gScriptFile);
-
- gScriptFile = gAppFile;
- }
-
- ShowWindowStatus();
-
- for (i=1; PerlArgs[i]; ++i)
- DisposPtr(PerlArgs[i]);
-
- switch (PerlQuit) {
- case 2:
- #ifdef RUNTIME
- case 1:
- #endif
- gQuitting = true;
- }
- }
-
- char * AEExtractor(void * data, int index)
- {
- DescType type;
- Size size;
- Boolean arg;
- AppleEvent * event;
- FSSpec spec;
- AEKeyword keywd;
- static AEDesc params = {'????', nil};
- char * retarg;
- char * path;
-
- event = (AppleEvent *) data;
-
- switch (index) {
- case extractDone:
- gRuntimeScript = nil;
-
- if (params.dataHandle)
- AEDisposeDesc(¶ms);
-
- return nil;
- case extractDir:
- if (gRuntimeScript
- || (!params.dataHandle
- && AEGetParamDesc(event, keyDirectObject, typeAEList, ¶ms))
- || AEGetNthPtr(
- ¶ms, 1, typeFSS, &keywd, &type,
- (Ptr) &spec, sizeof(FSSpec), &size)
- ) {
- spec.vRefNum = gAppVol;
- spec.parID = gAppDir;
- } else {
- short res = CurResFile();
-
- gScriptFile = HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
-
- if (gPseudoFile = Get1NamedResource('TEXT', "\p!")) {
- strcpy(gPseudoFileName, FSp2FullPath(&spec));
-
- DetachResource(gPseudoFile);
- }
-
- UseResFile(res);
- }
-
- FSpUp(&spec);
-
- return FSp2FullPath(&spec);
- case extractDebug:
- if (AEGetParamPtr(event, 'DEBG', typeBoolean, &type, (Ptr) &arg, 1, &size))
- return nil;
- else
- return arg ? "y" : "n";
- case extractCpp:
- if (AEGetParamPtr(event, 'PREP', typeBoolean, &type, (Ptr) &arg, 1, &size))
- return nil;
- else
- return arg ? "y" : "n";
- default:
- if (gRuntimeScript)
- --index;
- else if (index == 1 && gPseudoFile)
- return "Dev:Pseudo";
-
- if (!index) {
- gPseudoFile = gRuntimeScript;
-
- return "Dev:Pseudo";
- }
-
- if (!params.dataHandle)
- if (AEGetParamDesc(event, keyDirectObject, typeAEList, ¶ms))
- return nil;
-
- if (AEGetNthPtr(
- ¶ms, index, typeFSS,
- &keywd, &type,
- (Ptr) &spec, sizeof(FSSpec), &size)
- ) if (index == 1 && !gRuntimeScript) {
- AEDesc script;
-
- if (AEGetNthDesc(¶ms, index, typeChar, &keywd, &script))
- return nil;
-
- gPseudoFile = script.dataHandle;
-
- if (!gPseudoFileName[0])
- strcpy(gPseudoFileName, "<AppleEvent>");
-
- return "Dev:Pseudo";
- } else if (AEGetNthPtr(
- ¶ms, index, typeChar,
- &keywd, &type,
- nil, 0, &size)
- )
- return nil;
- else {
- retarg = NewPtr(size+1);
- retarg[size] = 0;
-
- if (AEGetNthPtr(
- ¶ms, index, typeChar,
- &keywd, &type,
- retarg, size, &size)
- ) {
- DisposPtr(retarg);
-
- return nil;
- } else
- return retarg;
- }
-
- path = FSp2FullPath(&spec);
- retarg = NewPtr(strlen(path)+1);
-
- strcpy(retarg, path);
-
- return retarg;
- }
- }
-
- char * StupidExtractor(void * data, int index)
- {
- FSSpec * spec;
- FSSpec dir;
- char * retarg;
- char * path;
-
- spec = (FSSpec *) data;
-
- switch (index) {
- case extractDone:
- case extractDebug:
- case extractCpp:
- return nil;
- case extractDir:
- dir = *spec;
-
- {
- short res = CurResFile();
-
- gScriptFile = HOpenResFile(dir.vRefNum, dir.parID, dir.name, fsRdPerm);
-
- if (gPseudoFile = Get1NamedResource('TEXT', "\p!")) {
- strcpy(gPseudoFileName, FSp2FullPath(spec));
-
- DetachResource(gPseudoFile);
- }
-
- UseResFile(res);
- }
-
- FSpUp(&dir);
-
- return FSp2FullPath(&dir);
- default:
- if (index > 1)
- return nil;
-
- if (gPseudoFile)
- return "Dev:Pseudo";
-
- path = FSp2FullPath(spec);
- retarg = NewPtr(strlen(path)+1);
-
- strcpy(retarg, path);
-
- return retarg;
- }
- }
-
- char * YeOldeExtractor(void * data, int index)
- {
- long count;
- char * retarg;
- char * path;
- FSSpec spec;
- AppFile arg;
-
- count = (long) data;
-
- switch (index) {
- case extractDone:
- gRuntimeScript = nil;
- case extractDebug:
- case extractCpp:
- return nil;
- case extractDir:
- if (gRuntimeScript) {
- spec.vRefNum = gAppVol;
- spec.parID = gAppDir;
- } else {
- short res = CurResFile();
-
- GetAppFiles(1, &arg);
-
- WD2FSSpec(arg.vRefNum, arg.fName, &spec);
-
- gScriptFile = HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
-
- if (gPseudoFile = Get1NamedResource('TEXT', "\p!")) {
- strcpy(gPseudoFileName, FSp2FullPath(&spec));
-
- DetachResource(gPseudoFile);
- }
-
- UseResFile(res);
- }
-
- FSpUp(&spec);
-
- return FSp2FullPath(&spec);
- default:
- if (index - (gRuntimeScript != 0) > count)
- return nil;
-
- if (gRuntimeScript)
- --index;
- else if (index == 1 && gPseudoFile)
- return "Dev:Pseudo";
-
- if (!index) {
- gPseudoFile = gRuntimeScript;
-
- return "Dev:Pseudo";
- }
-
- GetAppFiles(index, &arg);
-
- WD2FSSpec(arg.vRefNum, arg.fName, &spec);
-
- path = FSp2FullPath(&spec);
- retarg = NewPtr(strlen(path)+1);
-
- strcpy(retarg, path);
-
- return retarg;
- }
- }
-
- pascal OSErr DoScript(const AppleEvent *event, AppleEvent *reply, long refCon)
- {
- #pragma unused (refCon)
-
- if (gRunningPerl) {
- const AppleEvent * e[2];
-
- e[0] = event;
- e[1] = reply;
-
- PtrAndHand((Ptr) e, (Handle) gWaitingScripts, 8);
-
- return AESuspendTheCurrentEvent(event);
- }
-
- RunScript(AEExtractor, event);
-
- if (PerlReply) {
- HLock(PerlReply);
- AEPutParamPtr(
- reply, keyDirectObject,
- typeChar, *PerlReply, GetHandleSize(PerlReply));
- DisposeHandle(PerlReply);
- PerlReply = nil;
- }
-
- return noErr;
- }
-
- #ifdef RUNTIME
-
- pascal void DoScriptMenu(short theItem)
- {
- switch (theItem) {
- case pmRun:
- {
- Point wh;
- SFTypeList types;
- SFReply reply;
- FSSpec spec;
-
- wh.h = wh.v = 75;
- types[0] = 'TEXT';
- types[1] = 'APPL';
-
- SFGetFile(wh, "", GetScriptFilter, 2, types, (DlgHookProcPtr) nil, &reply);
-
- if (reply.good) {
- WD2FSSpec(reply.vRefNum, reply.fName, &spec);
-
- RunScript(StupidExtractor, &spec);
- }
- }
- break;
- case pmRunFront:
- {
- DPtr doc = DPtrFromWindowPtr(FrontWindow());
-
- if (!doc || doc->kind != kDocumentWindow)
- break;
-
- if (doc->dirty || !doc->u.reg.everSaved) {
- gRuntimeScript = (*doc->theText)->hText;
-
- HandToHand(&gRuntimeScript);
-
- if (doc->u.reg.everSaved)
- strcpy(gPseudoFileName, FSp2FullPath(&doc->theFSSpec));
- else
- getwtitle(FrontWindow(), gPseudoFileName);
-
- RunScript(YeOldeExtractor, (void *) 0);
- } else
- RunScript(StupidExtractor, &doc->theFSSpec);
- }
- break;
- }
- }
- #endif
-
- pascal Boolean DoRuntime()
- {
- short message;
- short count;
- FSSpec spec;
-
- if (gRuntimeScript = Get1NamedResource('TEXT', "\p!")) {
- spec.vRefNum = gAppVol;
- spec.parID = gAppDir;
- PLstrcpy(spec.name, (StringPtr) CurApName);
- strcpy(gPseudoFileName, FSp2FullPath(&spec));
-
- DetachResource(gRuntimeScript);
- }
-
- #ifndef RUNTIME
- return false;
- #else
- if (gAppleEventsImplemented)
- return false;
-
- CountAppFiles(&message, &count);
-
- if (count) {
- if (message == appPrint) {
- int i;
- AppFile arg;
-
- for (i=0; i++<count; ) {
- GetAppFiles(i, &arg);
-
- WD2FSSpec(arg.vRefNum, arg.fName, &spec);
-
- if (!IssueAEOpenDoc(spec)) {
- IssuePrintWindow(FrontWindow());
- IssueCloseCommand(FrontWindow());
- }
- }
-
- return true;
- }
- } else {
- if (!gRuntimeScript) {
- int i;
- AppFile arg;
-
- for (i=0; i++<count; ) {
- GetAppFiles(i, &arg);
-
- WD2FSSpec(arg.vRefNum, arg.fName, &spec);
-
- IssueAEOpenDoc(spec);
- }
-
- return false;
- }
- }
-
- RunScript(YeOldeExtractor, (void *) count);
-
- return gQuitting;
- #endif
- }
-